<script setup lang="ts" name="RoleEdit">
import { roleMenuTreeselectApi, treeMenuApi } from "@/api/system/menu";
import { addRoleApi, getRoleApi, updateRoleApi } from "@/api/system/role";

const { proxy } = getCurrentInstance();

const { sys_normal_disable } = useDict("sys_normal_disable")

const emit = defineEmits(['closeDialog']);

const props = defineProps({
  id: {
    default: null,
  },
  title: {
    type: String,
    default: false,
  }
})

// 角色管理表单
const roleFormRef = ref(null);

// 菜单树组件
const menuRef = ref(null);

// 菜单树列表
const menuList = ref<OptionRecord[]>([])

// 菜单树节点列表
const menuNodeList = ref<OptionRecord[]>([])

// 弹窗开关
const open = ref(false);

// 表单数据
const form = ref<RoleRecord>({});

// 展开/折叠
const menuExpand = ref(false);

// 全选/全不选
const deptNodeAll = ref(false);

// 表单校验
const rules = ref({
  roleName: [
    { required: true, message: "角色名称不能为空", trigger: "blur" },
  ],
  roleKey: [
    { required: true, message: "权限字符不能为空", trigger: "blur" },
  ],
  dataScope: [
    { required: true, message: "权限范围不能为空", trigger: "blur" },
  ],
  roleSort: [
    { required: true, message: "角色顺序不能为空", trigger: "blur" },
  ],
  status: [
    { required: true, message: "状态不能为空", trigger: "blur" },
  ],
});

// 加载
const loading = ref(false);

/** 获取角色管理详情 */
async function getData() {
  reset();
  if (isEmpty(props.id)) {
    open.value = true;
  } else {
    try {
      const response = await getRoleApi(props.id);
      form.value = response.data;
      open.value = true;
    } catch (err) {
      closeDialog(false);
    }
  }
  getTreeMenu();
}


/** 查询菜单树结构 */
async function getTreeMenu() {
  if (isEmpty(props.id)) {
    let { data } = await treeMenuApi();
    menuList.value = data;
  } else {
    let { checkedKeys, menus } = await roleMenuTreeselectApi(props.id);
    menuList.value = menus;
    menuRef.value.setCheckedKeys(checkedKeys);
  }
  menuNodeList.value = getAllMenuNode(menuList.value);
}

function getAllMenuNode(menuTreeList: OptionRecord[], nodeList: OptionRecord[] = []) {
  menuTreeList.forEach(item => {
    nodeList.push(item)
    if (item.children && item.children.length) {
      getAllMenuNode(item.children, nodeList)
    }
  })
  return nodeList;

}

/** 树权限（展开/折叠）*/
function handleCheckedTreeExpand(value) {
  const treeList = menuList.value;
  treeList.forEach(item => {
    menuRef.value.store.nodesMap[item.id].expanded = value;
  })
}

/** 树权限（全选/全不选） */
function handleCheckedTreeNodeAll(value) {
  menuRef.value.setCheckedNodes(value ? menuNodeList.value : []);
}

/** 树权限（父子联动） */
function handleCheckedTreeConnect(value) {
  form.value.menuCheckStrictly = value ? true : false;
}

/** 表单重置 */
function reset() {
  form.value = {
    roleId: null,
    roleName: null,
    roleKey: null,
    dataScope: null,
    roleSort: null,
    menuIds: [],
    permissions: [],
    status: SYS_NORMAL_DISABLE_ENUM.normal,
    deptCheckStrictly: null,
    remark: null,
  };
}

/** 关闭弹窗 */
function closeDialog(refresh: boolean) {
  open.value = false;
  emit("closeDialog", refresh);
}

/** 提交按钮 */
function submitForm() {
  roleFormRef.value.validate((valid: boolean) => {
    if (valid) {
      loading.value = true;
      form.value.menuIds = getMenuAllCheckedKeys();
      if (form.value.roleId) {
        updateRoleApi(form.value).then(() => {
          // @ts-ignore
          proxy.$modal.msgSuccess("修改成功");
          loading.value = false;
          closeDialog(true);
        }).catch(() => {
          loading.value = false
        });
      } else {
        addRoleApi(form.value).then(() => {
          // @ts-ignore
          proxy.$modal.msgSuccess("新增成功");
          loading.value = false;
          closeDialog(true);
        }).catch(() => {
          loading.value = false
        });
      }
    }
  })
}

/** 所有菜单节点数据 */
function getMenuAllCheckedKeys() {
  // 目前被选中的菜单节点
  const checkedKeys = menuRef.value.getCheckedKeys();
  // 半选中的菜单节点
  const halfCheckedKeys = menuRef.value.getHalfCheckedKeys();

  checkedKeys.unshift(...halfCheckedKeys)

  return checkedKeys;
}

watch(open, (val) => {
  if (!val) {
    closeDialog(false);
  }
})

getData();
</script>

<template>
  <!-- 角色管理编辑对话框 -->
  <el-dialog :title="title" v-model="open" width="736px" append-to-body :close-on-click-modal="false">
    <el-form ref="roleFormRef" :model="form" :rules="rules" :inline="true" label-width="98px">
      <el-form-item label="角色名称" prop="roleName">
        <el-input v-model="form.roleName" placeholder="请输入角色名称" />
      </el-form-item>
      <el-form-item label="权限字符" prop="roleKey">
        <template #label>
          <span>
            <el-tooltip content="控制器中定义的权限字符，如：admin)" placement="top">
              <icon-svg icon-name="QuestionFilled" />
            </el-tooltip>
            权限字符
          </span>
        </template>
        <el-input v-model="form.roleKey" placeholder="请输入权限字符" />
      </el-form-item>
      <el-form-item label="角色顺序" prop="roleSort">
        <el-input-number v-model="form.roleSort" :min="1" label="请输入角色顺序" />
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-radio-group v-model="form.status">
          <el-radio
              :value="item.value"
              v-for="(item, index) in sys_normal_disable"
              :key="index"
          >
            {{ item.label }}
          </el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="菜单权限" prop="menuIds" class="item-describe">
        <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand">展开/折叠</el-checkbox>
        <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll">全选/全不选</el-checkbox>
        <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect">父子联动</el-checkbox>
        <el-tree
            class="tree-border"
            :data="menuList"
            show-checkbox
            ref="menuRef"
            node-key="id"
            :check-strictly="!form.menuCheckStrictly"
            empty-text="加载中，请稍候"
            :props="{ label: 'label', children: 'children' }"
        />
      </el-form-item>
      <el-form-item label="备注" prop="remark" class="item-describe">
        <el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" v-debounce="submitForm" :loading="loading">确 定</el-button>
        <el-button @click="closeDialog(false)">取 消</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped>
.tree-border{
  min-height: 100px;
  max-height: 300px;
  overflow-y: auto;
}
</style>